package proiectpcbe;

import java.util.ArrayList;

/**
 *
 * @author Ady
 */
class ResurseJucator {

    private int LEMN;
    private int PIATRA;
    private int METAL;

    public ResurseJucator(int lemn, int piatra, int metal) {
        this.LEMN = lemn;
        this.PIATRA = piatra;
        this.METAL = metal;
    }

    public int getLemn() {
        return this.LEMN;
    }

    public int getPiatra() {
        return this.PIATRA;
    }

    public int getMetal() {
        return this.METAL;
    }

    public void setLemn(int lemn) {
        this.LEMN = lemn;
    }

    public void setPiatra(int piatra) {
        this.PIATRA = piatra;
    }

    public void setMetal(int metal) {
        this.METAL = metal;
    }

    public boolean existaResurse(ResurseJucator res) {
        return this.LEMN >= res.getLemn() && this.PIATRA >= res.getPiatra() && this.METAL >= res.getMetal();
    }

    public void consumaResurse(ResurseJucator res) {
        this.LEMN = this.LEMN - res.getLemn();
        this.PIATRA = this.PIATRA - res.getPiatra();
        this.METAL = this.METAL - res.getMetal();
    }
}

public class Jucator extends Thread {

    private ResurseJucator resurse;
    private ArrayList<Cladire> cladiri;
    private Cladire target;
    private Comert comert;
    private Resurse res;
    private int puncte;
    private boolean stop;
    private StartJoc m_joc;
    private final Object m_lockLista = new Object();
    private ArrayList<CladireDeResurse> m_lista;

    public Jucator(StartJoc joc, Comert com, Resurse rs, String nume) {
        m_joc = joc;
        resurse = new ResurseJucator(10, 5, 2);
        cladiri = new ArrayList<Cladire>(0);
        m_lista = new ArrayList<CladireDeResurse>();
        target = Cladire.daCladire();
        comert = com;
        res = rs;
        puncte = 0;
        setName(nume);
    }

    public void stopPlayer() {
        stop = true;
    }

    @Override
    public void run() {
        while (target != null && puncte < 1000 && !stop) {
            if (construieste()) {
                puneOferte();
            } else {
                anuleazaOferte();
                if (construieste()) {
                    puneOferte();
                } else {
                    iaResurseProducator();
                }
            }
        }
        if (!stop) {
            System.err.println(getName() + " a facut " + puncte);
            m_joc.stopJoc();
        } else {
            System.out.println(getName() + " a facut " + puncte);
        }
        synchronized (m_lockLista) {
            for (CladireDeResurse c : m_lista) {
                c.interrupt();
            }
        }
        m_lista = null;
    }

    private boolean construieste() {

        synchronized (resurse) {
            StartJoc.debug(getName() + "            ---- CONSTRUIESTE ----");
            StartJoc.debug(getName() + "  Resurse existente : " + resurse.getLemn() + " lemn, " + resurse.getPiatra() + " piatra, " + resurse.getMetal() + " metal");
            StartJoc.debug(getName() + "  Construieste cladira " + target.getNumeCladire() + " ( " + target.getResurse().getLemn() + " lemn, " + target.getResurse().getPiatra() + " piatra, " + target.getResurse().getMetal() + " metal )");
            if (resurse.existaResurse(target.getResurse())) {
                this.cladiri.add(target);
                StartJoc.debug(getName() + "  S-a construit cladirea!!");
                System.out.println(getName() + " a construit " + target.getNumeCladire());
                resurse.consumaResurse(target.getResurse());
                puncte = puncte + target.getValoare();
                StartJoc.debug(getName() + "  Resurse ramase: " + resurse.getLemn() + " lemn, " + resurse.getPiatra() + " piatra, " + resurse.getMetal() + " metal");
                cladireConstruita(target);
                target = Cladire.daCladire();
                StartJoc.debug(getName() + "  Cladirea urmatoare: " + target.getNumeCladire() + " ( " + target.getResurse().getLemn() + " lemn, " + target.getResurse().getPiatra() + " piatra, " + target.getResurse().getMetal() + " metal )");
                return true;
            }
            StartJoc.debug(getName() + "  Resurse insuficiente!!");
            return false;
        }
    }

    private void cladireConstruita(Cladire c) {
        if (c.creazaResurse()) {
            CladireDeResurse clad = new CladireDeResurse(c.getResursaConstruita(), c.getCantConstruita(), c.getTimpDeConstruit());
            synchronized (m_lockLista) {
                m_lista.add(clad);
            }
            clad.start();
        }
    }

    private void puneOferte() {
        int dif_Lemn, dif_Piatra, dif_Metal, cantitate = -1;
        Resursa oferita = null, ceruta = null;
        synchronized (resurse) {
            dif_Lemn = resurse.getLemn() - target.getResurse().getLemn();
            dif_Piatra = resurse.getPiatra() - target.getResurse().getPiatra();
            dif_Metal = resurse.getMetal() - target.getResurse().getMetal();
            if (dif_Lemn > 0) {
                oferita = Resursa.LEMN;
                cantitate = dif_Lemn;
                resurse.setLemn(resurse.getLemn() - dif_Lemn);
                if (dif_Piatra < 0) {
                    ceruta = Resursa.PIATRA;
                } else {
                    ceruta = Resursa.METAL;
                }
            } else if (dif_Piatra > 0) {
                oferita = Resursa.PIATRA;
                cantitate = dif_Piatra;
                resurse.setPiatra(resurse.getPiatra() - dif_Piatra);
                if (dif_Lemn < 0) {
                    ceruta = Resursa.LEMN;
                } else {
                    ceruta = Resursa.METAL;
                }
            } else if (dif_Metal > 0) {
                oferita = Resursa.METAL;
                cantitate = dif_Metal;
                resurse.setMetal(resurse.getMetal() - dif_Metal);
                if (dif_Lemn < 0) {
                    ceruta = Resursa.LEMN;
                } else {
                    ceruta = Resursa.PIATRA;
                }
            }
        }
        if (cantitate > 0) {
            comert.puneOferta(this, cantitate, oferita, ceruta);
            StartJoc.debug(getName() + "            ---- PUNE OFERTE ----");
            StartJoc.debug(getName() + "  S-a pus oferta : " + cantitate + " " + oferita + " pe " + ceruta);
            StartJoc.debug(getName() + "  Resurse ramase: " + resurse.getLemn() + " lemn, " + resurse.getPiatra() + " piatra, " + resurse.getMetal() + " metal");

        }
    }

    private void anuleazaOferte() {
        int dif_Lemn, dif_Piatra, dif_Metal, cantitate, max;
        Resursa oferita, primaCeruta, aDouaCeruta;

        synchronized (this.resurse) {

            dif_Lemn = resurse.getLemn() - target.getResurse().getLemn();
            max = cantitate = dif_Lemn;
            primaCeruta = aDouaCeruta = oferita = Resursa.LEMN;
            dif_Piatra = resurse.getPiatra() - target.getResurse().getPiatra();
            if (dif_Piatra < cantitate) {
                cantitate = dif_Piatra;
                oferita = Resursa.PIATRA;
            }
            if (dif_Piatra > max) {
                max = dif_Piatra;
                primaCeruta = Resursa.PIATRA;
            }
            dif_Metal = resurse.getMetal() - target.getResurse().getMetal();
            if (dif_Metal < cantitate) {
                cantitate = dif_Metal;
                oferita = Resursa.METAL;
            }
            if (dif_Metal > max) {
                max = dif_Metal;
                primaCeruta = Resursa.METAL;
            }
            StartJoc.debug(getName() + "            ---- ANULEAZA OFERTE ----");
            StartJoc.debug(getName() + "  Anuleaza oferta. Resurse necesare: " + dif_Lemn + " lemn, " + dif_Piatra + " piatra, " + dif_Metal + " metal");
            if (oferita == Resursa.LEMN && primaCeruta == Resursa.METAL || oferita == Resursa.METAL && primaCeruta == Resursa.LEMN) {
                aDouaCeruta = Resursa.PIATRA;
            }
            if (oferita == Resursa.LEMN && primaCeruta == Resursa.PIATRA || oferita == Resursa.PIATRA && primaCeruta == Resursa.LEMN) {
                aDouaCeruta = Resursa.METAL;
            }
            if (oferita == Resursa.PIATRA && primaCeruta == Resursa.METAL || oferita == Resursa.METAL && primaCeruta == Resursa.PIATRA) {
                aDouaCeruta = Resursa.LEMN;
            }
            StartJoc.debug(getName() + "  Apel: comert.anuleazaOferta( this, " + oferita + ", " + (-1) * cantitate + ", " + primaCeruta + ", " + aDouaCeruta + " );");
            comert.anuleazaOferta(this, oferita, -cantitate, primaCeruta, aDouaCeruta);
        }
    }

    public void vinResurseDinComert(int cantitate, Resursa res) {
        synchronized (this.resurse) {
            switch (res) {
                case LEMN:
                    this.resurse.setLemn(this.resurse.getLemn() + cantitate);
                    break;
                case PIATRA:
                    this.resurse.setPiatra(this.resurse.getPiatra() + cantitate);
                    break;
                case METAL:
                    this.resurse.setMetal(this.resurse.getMetal() + cantitate);
                    break;
            }
            StartJoc.debug(getName() + "            ---- RESURSE DIN COMERT");
            StartJoc.debug(getName() + "  Resurse primite din comert : " + cantitate + " " + res);
            StartJoc.debug(getName() + "  Resurse cumulate : " + resurse.getLemn() + " lemn, " + resurse.getPiatra() + " piatra, " + resurse.getMetal() + " metal");


        }
    }

    private void iaResurseProducator() {
        int nrResPrimite;
        Resursa resCeruta;
        StartJoc.debug(getName() + "            ---- RESURSE PRODUCATOR ----");
        synchronized (this.resurse) {

            if (resurse.getLemn() - target.getResurse().getLemn() < 0) {
                resCeruta = Resursa.LEMN;
            } else if (resurse.getPiatra() - target.getResurse().getPiatra() < 0) {
                resCeruta = Resursa.PIATRA;
            } else {
                resCeruta = Resursa.METAL;
            }
        }
        Producator p = this.res.getProducator(resCeruta);
        if (p != null) {
            nrResPrimite = p.da_resurse();
            synchronized (this.resurse) {
                switch (resCeruta) {
                    case LEMN:
                        this.resurse.setLemn(this.resurse.getLemn() + nrResPrimite);
                        break;
                    case PIATRA:
                        this.resurse.setPiatra(this.resurse.getPiatra() + nrResPrimite);
                        break;
                    case METAL:
                        this.resurse.setMetal(this.resurse.getMetal() + nrResPrimite);
                        break;
                }
            }
            res.adaugaProducator(p);
            StartJoc.debug(getName() + "  Resurse primite: " + nrResPrimite + " " + resCeruta);
            StartJoc.debug(getName() + "  Resurse cumulate : " + resurse.getLemn() + " lemn, " + resurse.getPiatra() + " piatra, " + resurse.getMetal() + " metal");


        } else {
            StartJoc.debug(getName() + "  Nu s-a gasit niciun producator liber !!!");
        }
    }

    private void addResurseCladire(Resursa res, int cantitate) {
        //System.out.println(getName() + " resurse din cladire " + res + " " + cantitate);
        synchronized (this.resurse) {
            switch (res) {
                case LEMN:
                    this.resurse.setLemn(this.resurse.getLemn() + cantitate);
                    break;
                case PIATRA:
                    this.resurse.setPiatra(this.resurse.getPiatra() + cantitate);
                    break;
                case METAL:
                    this.resurse.setMetal(this.resurse.getMetal() + cantitate);
                    break;
            }
        }
    }

    private class CladireDeResurse extends Thread {

        private Resursa res;
        private int cant, timp;

        public CladireDeResurse(Resursa res, int cant, int timp) {
            this.res = res;
            this.cant = cant;
            this.timp = timp;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    Jucator.this.addResurseCladire(res, cant);
                    synchronized (this) {
                        wait(timp);
                    }
                }
            } catch (InterruptedException ex) {
                System.out.println("End cladire de resurse");
            }
        }
    }
}
